Connectomes¶

NiiVue considers connectomes as a special class of meshes. While most meshes have fixed vertex positions (e.g. a brain is considered to have a fixed size), the radius of connectome nodes and edges can be scaled dynamically. The notebook mirrors the JavaScript connectome web page.

In [1]:
from pathlib import Path

from ipyniivue import download_dataset

BASE_API_URL = "https://niivue.com/demos/images/"
DATA_FOLDER = Path("images")

# Download data for example
download_dataset(
    BASE_API_URL,
    DATA_FOLDER,
    files=[
        "mni152.nii.gz",
        "connectome.jcon",
    ],
)
mni152.nii.gz already exists.
connectome.jcon already exists.
Dataset downloaded successfully to images.
In [2]:
import ipywidgets as widgets
from IPython.display import display

from ipyniivue import NiiVue

nv = NiiVue(show_3d_crosshair=True, is_colorbar=True, back_color=(0.8, 0.8, 1, 1))

nv.load_volumes([{"path": DATA_FOLDER / "mni152.nii.gz"}])
nv.load_meshes([{"path": DATA_FOLDER / "connectome.jcon"}])
nv.volumes[0].colorbar_visible = False
nv.set_clip_plane(0.1, 0, 135)
nv.opts.mesh_xray = 0.1

# Create UI

edge_scale_slider = widgets.FloatSlider(
    value=1, min=0.5, max=3, step=0.1, description="Edge", readout=False
)


def on_edge_scale_change(change):
    """Set size of edges."""
    nv.meshes[0].edge_scale = change["new"]


edge_scale_slider.observe(on_edge_scale_change, names="value")

node_scale_slider = widgets.FloatSlider(
    value=3, min=0.5, max=6, step=0.1, description="Node", readout=False
)


def on_node_scale_change(change):
    """Set size of nodes."""
    nv.meshes[0].node_scale = change["new"]


node_scale_slider.observe(on_node_scale_change, names="value")

legend_slider = widgets.IntSlider(
    value=0, min=0, max=12, description="Legend lines", readout=False
)


def on_legend_change(change):
    """Set size of legend lines."""
    nv.meshes[0].legend_line_thickness = change["new"]


legend_slider.observe(on_legend_change, names="value")

options = list(range(1, 60))

stat_range = widgets.SelectionRangeSlider(
    options=options,
    index=(10, 50),
    description="Threshold:",
    disabled=False,
    readout=False,
)


def on_stat_change(change):
    """Set threshold for statistical overlay."""
    low, high = change["new"]
    nv.meshes[0].edge_min = low * 0.1
    nv.meshes[0].edge_max = high * 0.1


stat_range.observe(on_stat_change, names="value")

# Display
controls = widgets.HBox(
    [edge_scale_slider, node_scale_slider, legend_slider, stat_range]
)

display(widgets.VBox([controls, nv]))